package com.tplhk.batch.common;

import com.tplhk.batch.useParameter.UserInfo;
import com.tplhk.batch.useParameter.UserInfos;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.builder.FlowBuilder;
import org.springframework.batch.core.job.flow.Flow;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

/**
 * @ClassName : JobDemo
 * @Description : TODO
 * @Author : taiping
 * @Date: 2020/12/14 11:41
 **/
@Configuration
@EnableBatchProcessing
public class CommonSteps implements StepExecutionListener {

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private CommonService commonService;

    @Autowired
    UserInfos userInfos;

    @Autowired
    CommonDemoStep2Tasklet commonDemoStep2Tasklet;


    @Bean
    public Flow commonDemoFlow1() {
        return new FlowBuilder<Flow>("commonDemoFlow1")
                .start(commonDemoStep1())
                .build();
    }

    @Bean
    public Flow commonDemoFlow23() {
        return new FlowBuilder<Flow>("commonDemoFlow23")
                .start(commonDemoStep2())
                .next(commonDemoStep3())
                .build();
    }

    /**
     * tasklet 学习 1： 可以执行两步操作，并且可以在 tasklet 中定义参数 result
     *
     * @return
     */
    @Bean
    public Step commonDemoStep1() {
        return this.stepBuilderFactory.get("commonDemoStep1")
                .tasklet((contribution, chunkContext) -> {
                    String result = commonService.testService1();
                    commonService.testServiceParam(result);
                    return RepeatStatus.FINISHED;
                }).build();
    }

    /**
     * tasklet学习 2：单独创建 tasklet 类
     *
     * @return
     */
    @Bean
    public Step commonDemoStep2() {
        return stepBuilderFactory.get("commonDemoStep2").tasklet(commonDemoStep2Tasklet).build();
    }

    @Bean
    public Step commonDemoStep3() {
        return stepBuilderFactory.get("commonDemoStep3").tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("commonDemoStep3");
                return RepeatStatus.FINISHED;
            }
        }).build();
    }

    /**
     * tasklet 学习 3： 外部传参和内部传参到 step
     *
     * @return
     */
    @Bean
    public Step commonDemoStep4() {
        return this.stepBuilderFactory.get("commonDemoStep4")
                .listener(this)
                .tasklet((contribution, chunkContext) -> {
                    commonService.testServiceParam((String) chunkContext.getStepContext().getJobParameters().get("time"));
                    commonService.testServiceParam(userInfos.getUserInfoList().toString());
                    return RepeatStatus.FINISHED;
                }).build();
    }

    /**
     * tasklet 学习 4： 异常处理，设置status ，将会中止后面的 step 执行
     *
     * @return
     */
    @Bean
    public Step errorStep() {
        return stepBuilderFactory.get("errorStep").tasklet((stepContribution, chunkContext) -> {
            System.out.println("errorStep.........");
            // 下面设置的 status ，将会中止后面的 step 执行
            chunkContext.getStepContext().getStepExecution().setStatus(BatchStatus.FAILED);
            return RepeatStatus.FINISHED;
        }).build();
    }

    @Override
    public void beforeStep(StepExecution stepExecution) {
        // 内部传参
        userInfos.getUserInfoList().add(UserInfo.builder().id("11").name("xjq").build());

    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        return null;
    }
}
